//
//  GLWaterFlowView.m
//  GLWaterFlowView
//
//  Created by CoderGL on 15/11/27.
//  Copyright © 2015年 GL. All rights reserved.
//

#import "GLWaterFlowView.h"
#import "GLWaterFlowViewCell.h"


#define GLWaterFlowViewCellDefaultMargin 10
#define GLWaterFlowViewCellDefaultHeight 70
#define GLWaterflowViewDefaultNumberOfColumns 3
@interface GLWaterFlowView ()

@property (nonatomic, strong) NSMutableArray *cellFrames;
@property (nonatomic, strong) NSMutableDictionary *displayingCells;
@property (nonatomic, strong) NSMutableSet *reusableCells;

@end



@implementation GLWaterFlowView

- (NSMutableSet *)reusableCells {
    if (!_reusableCells) {
        _reusableCells = [NSMutableSet set];
    }
    return _reusableCells;
}

- (NSMutableDictionary *)displayingCells {
    if (!_displayingCells) {
        _displayingCells = [NSMutableDictionary dictionary];
    }
    return _displayingCells;
}

- (NSMutableArray *)cellFrames {
    if (!_cellFrames) {
        _cellFrames = [NSMutableArray array];
    }
    return _cellFrames;
}



- (void)reloadData {
    
    // 清空之前的所有数据
    // 移除正在正在显示cell
    [self.displayingCells.allValues enumerateObjectsUsingBlock:^(GLWaterFlowViewCell *  _Nonnull cell, NSUInteger idx, BOOL * _Nonnull stop) {
        [cell removeFromSuperview];
    }];
    [self.displayingCells removeAllObjects];
    [self.cellFrames removeAllObjects];
    [self.reusableCells removeAllObjects];
    
    
    // 1.获得cell的总数
    NSUInteger cells = [self.dataSource numberOfCellsInWaterFlowView:self];
    
    // 2.获得总列数
    NSUInteger columns = [self.dataSource numberOfColumnInWaterFlowView:self];
    
    // 3.算出 上下左右 以及 每行 每列 的间距 向数据源索要
    CGFloat marTop = [self marginForType:GLWaterFlowViewTypeTop];
    CGFloat marBottom = [self marginForType:GLWaterFlowViewTypeBottom];
    CGFloat marLeft = [self marginForType:GLWaterFlowViewTypeLeft];
    CGFloat marColumn = [self marginForType:GLWaterFlowViewTypeColumn];
    CGFloat marRow = [self marginForType:GLWaterFlowViewTypeRow];
    
    // 4.计算cell的宽度
    CGFloat cellW = [self cellWidth];
    
    // 5.用C语言数组 存放所有列的最大Y值
    CGFloat maxYs[columns];
    for (int i = 0; i < columns; i++) { // 初始化数组
        maxYs[i] = 0;
    }
    
    // 6.计算所有cell的frame
    for (int i = 0; i < cells; i++) { // 循环便利所有cell
        // 最短那一列的列号
        NSUInteger defaultColumn = 0;
        // 最短那列最大的Y值
        CGFloat maxYOfminColumn = maxYs[defaultColumn];

        for (int j = 1; j < columns; j++) { // 遍历最大Y值的数组
            if (maxYs[j] < maxYOfminColumn) { // 如果发现有比 最短那列最大的Y值 还小的那么就重新赋值;
                defaultColumn = j;
                maxYOfminColumn = maxYs[j];
            }
            
        }
        
        // 询问代理i位置的高度
        CGFloat cellH = [self heightAtIndex:i];
        
        // cell的位置
        CGFloat cellX = marLeft + (cellW + marColumn) * defaultColumn;
        CGFloat cellY = 0;
        
        if (maxYOfminColumn == 0.0) {
            cellY = marTop;
        } else {
            cellY = maxYOfminColumn + marRow;
        }
        
        // 计算出的 cell的frame 并添加到数组中
        CGRect cellFrame = CGRectMake(cellX, cellY, cellW, cellH);
        [self.cellFrames addObject:[NSValue valueWithCGRect:cellFrame]];
        
        // 更新C数组中最短那列的最大Y值
        maxYs[defaultColumn] = CGRectGetMaxY(cellFrame);
    }
    
    // 设置contentSize
    
    CGFloat contentH = maxYs[0];
    for (int i = 1; i < columns; i++) {
        if (maxYs[i] > contentH) {
            contentH = maxYs[i];
        }
    }
    contentH += marBottom;
    
    self.contentSize = CGSizeMake(0, contentH);
}


/**
 *  当scrollView 滚动时候 也会掉用这个方法
 */
- (void)layoutSubviews {
    [super layoutSubviews];
    // 想数据源索要对应位置的Cell
    NSUInteger numberOfCells = self.cellFrames.count;
    NSLog(@"%d", numberOfCells);
    for (int i = 0; i<numberOfCells; i++) {
        CGRect cellFrame = [self.cellFrames[i] CGRectValue];
        
        // 优先从字典中取出i位置对应的cell
        GLWaterFlowViewCell *cell = self.displayingCells[@(i)];
        
        // 判断i位置对应的cell 是否在屏幕上 （能否看见）
        
        if ([self isVisibility:cellFrame]) { // 可见(cell要显示出来)
            if (cell == nil) { // 如果不存在就向数据源要一个
                cell = [self.dataSource waterFlowView:self cellAtIndex:i];
                cell.frame = cellFrame;
                [self addSubview:cell];
                
                // 存进字典 (为了防治拖动一点点就重复添加)
                self.displayingCells[@(i)] = cell;
            }
        } else {
            if (cell) { // 如果不在屏幕上并且cell存在就从字典中移除 将他的frame从数组中移除
                [cell removeFromSuperview];
                [self.displayingCells removeObjectForKey:@(i)];
                
                // 存放进缓存池
                [self.reusableCells addObject:cell];
            }
        }
    }
    
}

/**
 *  从缓存池中取cell
 */
- (GLWaterFlowViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier {
    
    __block GLWaterFlowViewCell *reuseCell = nil;
    
    [self.reusableCells enumerateObjectsUsingBlock:^(GLWaterFlowViewCell *  _Nonnull cell, BOOL * _Nonnull stop) {
        if ([cell.identifier isEqualToString:identifier]) {
            reuseCell = cell;
            *stop = YES;
        }
    }];
    
    if (reuseCell) { // 从缓存池中移除
        [self.reusableCells removeObject:reuseCell];
    }
    
    
    return reuseCell;
}

/**
 *  cell的宽度
 */
- (CGFloat)cellWidth
{
    // 总列数
    int numberOfColumns = [self numberOfColumns];
    CGFloat leftM = [self marginForType:GLWaterFlowViewTypeLeft];
    CGFloat rightM = [self marginForType:GLWaterFlowViewTypeRight];
    CGFloat columnM = [self marginForType:GLWaterFlowViewTypeColumn];
    return (self.bounds.size.width - leftM - rightM - (numberOfColumns - 1) * columnM) / numberOfColumns;
}





#pragma mark - privite Method

/**
 *  判断是否可见
 */
- (BOOL)isVisibility:(CGRect)frame {
    return (CGRectGetMaxY(frame) > self.contentOffset.y) &&
    (CGRectGetMinY(frame) < self.contentOffset.y + self.bounds.size.height);
}

/**
 *  index位置的cell的高度
 */
- (CGFloat)heightAtIndex:(NSUInteger)index {
    if ([self.delegate respondsToSelector:@selector(waterFlowView:heightAtIndex:)]) {
        return [self.delegate waterFlowView:self heightAtIndex:index];
    } else {
        return GLWaterFlowViewCellDefaultHeight;
    }
}

/**
 *  间距
 */
- (CGFloat)marginForType:(GLWaterFlowViewType)type {
    if ([self.delegate respondsToSelector:@selector(waterFlowView:waterFlowViewType:)]) {
        return [self.delegate waterFlowView:self waterFlowViewType:type];
    } else {
        return GLWaterFlowViewCellDefaultMargin;
    }
}

/**
 *  总列数
 */
- (NSUInteger)numberOfColumns
{
    if ([self.dataSource respondsToSelector:@selector(numberOfColumnsInWaterflowView:)]) {
        return [self.dataSource numberOfColumnInWaterFlowView:self];
    } else {
        return GLWaterflowViewDefaultNumberOfColumns;
    }
}


/**
 *  即将添加到父控件时掉用（即将从父控件移除也会掉用）
 */
- (void)willMoveToSuperview:(UIView *)newSuperview
{
    [self reloadData];
}


/**
 *  cell触摸时间处理
 */
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
     //  如果代理没有响应到点击事件直接返回
    if (![self.delegate respondsToSelector:@selector(waterFlowView:didSelectAtIndex:)]) {
        return;
    }
    
    // 得到触摸点
    UITouch *touch = [touches anyObject];
    CGPoint point = [touch locationInView:self];
    
    // 记录触摸到的cell的索引
    __block NSNumber *selectIndex = nil;
    [self.displayingCells enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, GLWaterFlowViewCell *  _Nonnull cell, BOOL * _Nonnull stop) {
        if (CGRectContainsPoint(cell.frame, point)) {
            selectIndex = key;
            *stop = YES;
        }
    }];
    
    
    if (selectIndex) { // 掉用代理方法 并把索引传出去
        [self.delegate waterFlowView:self didSelectAtIndex:selectIndex.unsignedIntegerValue];
    }
}




@end
